package com.base.service;

import java.sql.Timestamp;
import java.util.*;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import tool.ClientTool;
import tool.JsonTool;
import tool.TimeTool;

import com.base.bean.*;
import com.base.dao.*;
import com.base.domain.*;

/**
 * 待完成功能： getDetailByCid() getList(int con,int page,int isDesc)
 * con可以是：1/2/3/4/5的形式 单选按钮的值
 * 
 * @author Administrator
 * 
 */

@Deprecated
public class ClientService {

	// 单例模式 start
	private volatile static ClientService instance = null;
	private ClientPhoneDao clientPhoneDao;
	private ClientBaseDao clientBaseDao;
	private ClientExtendDao clientExtendDao;

	// 条件查询需要用到的枚举类型
	static enum QUERY_TYPE {
		DEFAULT, MODIFIED, CREATED, CLIENT_TYPE, SELL_PLAN, CITY, PROVINCE
	}

	
	
	private ClientService() {
		clientPhoneDao = (ClientPhoneDao) _BaseDao.ac.getBean("ClientPhoneDao");
		clientBaseDao = (ClientBaseDao) _BaseDao.ac.getBean("ClientBaseDao");
		clientExtendDao = (ClientExtendDao) _BaseDao.ac.getBean("ClientExtendDao");
	}

	
	public static ClientService getInstance() {
		if (instance == null) {
			synchronized (ClientService.class) {// 1
				if (instance == null) {// 2
					instance = new ClientService();// 3
				}
			}
		}
		return instance;
	}

	// 单例模式 end

	// 点赞应该将当时的信息给持久化保存到一个表中 然后可以查看自己点了哪些赞
	// 点赞应该是一个ajax操作，且可以反复 一天后才不能修改

	/**
	 * 关于编辑修改作废客户信息的思路： 编辑自己创建的客户 事务管理 编辑客户信息： 1）非自己创建的客户只能编辑扩展信息
	 * （不用考虑添加电话，如果电话不一样，还不如新建一个！） 2）同时也不用考虑修改的历史记录
	 * 这些在作废的时候统一存放到waste_info表中,只能后续技术分析 在线分析意义不大
	 * 3）关于状态信息改变的及时确认，最好还是通过行动来确认，行动会将客户的基本信息固化下来
	 * 
	 * 因此： 非自己创建的客户只能编辑扩展信息 自己创建的客户可以任意编辑信息 作废信息时，将整个对象copy到waste_info表中
	 * 前台表单元素是否只读要设置相一致 表单中的基本信息和扩展信息基本和表中设置一致（除了memo为了便于查看，将本该扩展信息的字段放到基础信息中）
	 * 
	 * 待完善： 对经纪人给赞 应该只能给一次机会（一天之内应该视为一次），后续再完善 设置默认电话 怎么设置
	 * 
	 */

	/**
	 * 功能：编辑客户信息（分两种情况：自建/非自建） cPhones只用有电话信息即可（一旦有重复 整个事务会提交不进去）
	 * 编辑模式的电话修改遵循：先看是否存在，若不存在先判格式 判重 然后再添加
	 * 
	 */
	public boolean editClient(Boolean isOwn, ClientBase cBase,
			ClientExtend cExtend, String strPhones) {
		// 若是自建客户 修改电话则先删除电话再添加电话，添加时依然要进行检查
		// checkPhone

		Session session = clientBaseDao.getSessionFactory().getCurrentSession();
		try{
		Transaction tx = session.beginTransaction();

		Integer cid = cBase.getCid();
		Timestamp current = TimeTool.getCurrentTime();
		if (isOwn) {
			try {
				cBase.setModified(current); // cBase 修改时间
				session.update(cBase);
				cExtend.setModified(current);
				session.update(cExtend);

				String[] phones = strPhones.split("\\|");
				for (String phone : phones) {

					ClientPhone clientPhone = new ClientPhone(phone);
					clientPhone.setCid(cid);
					clientPhone.setCreator(cBase.getCreator()); // 添加电话 需要将设置创建人
					clientPhone.setCreated(current);
					session.update(clientPhone);
				}
				tx.commit();
				return true;
			} catch (Exception e) {
				tx.rollback();
				e.printStackTrace();
				return false;
			}
		} else { // 非自建客户
			cExtend.setModified(current);
			session.update(cExtend);
			tx.commit();
			return true;
		}
		}finally{
			session.close();
		}
	}
	
	public int updateLastTime(Integer cid){
		Session session=null;
		Transaction tx = null;
		try{
		session = clientBaseDao.getSessionFactory().getCurrentSession();
		tx = session.beginTransaction();	
		String hql = "update ClientBase cb set cb.lastTime = :currentTime where cb.cid = :cid";
		Query query = session.createQuery(hql);
		
		query.setTimestamp("currentTime", TimeTool.getCurrentTime());
		query.setInteger("cid", cid);
		
		int r =  query.executeUpdate();
		tx.commit();
		return r;
		}catch(Exception e){
			e.printStackTrace();
			tx.rollback();
			return 0;
		}finally{
			if(session.isOpen())
				session.close();
		}
		
	}

	
	/**
	 * 相同city的客户不能重名 （如果是修改模式-cid>0 则不能与cid以外的相同）
	 * @return
	 */
	public boolean isNameCityRepeat(String name,String cityId,Integer cid){
	try{	
		int count=0;
//		System.out.println(cid+"#####");
		if(cid>0)		//相当于修改模式  （其实可以省略else分支）
			count=clientBaseDao.findByHql("from ClientBase cb where cb.name='"+name+"' and cb.cityId='"+cityId+"' and cb.cid<>"+cid).size();	
		else		//新增模式
			count=clientBaseDao.findByHql("from ClientBase cb where cb.name='"+name+"' cb.cityId='"+cityId+"'").size();
			

		if(count>0)			
			return false;	
		else	
			return true;
		
	}catch(Exception e){
		e.printStackTrace();		
		return false;
	}
		
	}
	
	public String getName(Integer cid){
	try{	
		return this.clientBaseDao.findByHql("from ClientBase a where a.cid="+cid).get(0).getName();
	}catch(Exception e){
		e.printStackTrace();
		return "";
	}
	}
	
	
	
	/**
	 * 已经推荐
	 * @param cid
	 * @return
	 */
	public boolean isRemind(Integer cid){
		try{
		ClientBase cb=clientBaseDao.findByHql("from ClientBase cb where cb.cid="+cid).get(0);
		cb.setIsRemind(2);
		clientBaseDao.merge(cb);
		return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
	}
	
	/**
	 * phones(***|***|***) 验证自己的客户电话
	 * 
	 * @return
	 */
	private Map<String, String> checkOwnPhones(Integer cid, Integer creator,
			String phones) {
		Map<String, String> phoneMap = new HashMap<String, String>();
		String[] phoneArr = phones.split("\\|");
		for (int i = 0; i < phoneArr.length; i++) {
			try {
				ClientPhone _phone = clientPhoneDao.findByExample(
						new ClientPhone(phoneArr[i])).get(0);
				phoneMap.put(phoneArr[i], "exit");
			} catch (Exception e) {
				if (ClientTool.isMobileNO(phoneArr[i]))
					phoneMap.put(phoneArr[i], "new");
				else
					phoneMap.put(phoneArr[i], "error");
			}

		}

		return phoneMap;
	}

	/**
	 * 功能： 事务添加ClientBase 然后查询cid 以cid作为关联id 插入ClientExtend ClientPhone
	 * 并自动添加到clientOwner 返回值：成功 maxId(即当前新增的客户id) 否则返回0
	 * 
	 * 待完善： 通过返回几种状态实现json格式验证和此方法整合，意义不大？
	 * 
	 * @throws Exception
	 */

	public Integer addClient(ClientBase cBase, ClientExtend cExtend,
			List<ClientPhone> phoneList) throws Exception {
		// ###############实际替换##################
		Integer owner = new Integer(1);
		Integer creator = new Integer(1);
		Integer originId = 0; // 非经纪人推荐客户 originId设为0
		// #########################################

		try {
			if (cBase.getCid() != null) { // 若cid不为空 表示不是新客户
//				System.out.println(cBase.getCid().toString());
				throw new Exception("不是新客户，无法新增");

			}
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}

		Session session = clientBaseDao.getSessionFactory().getCurrentSession();
		Transaction tx = session.beginTransaction();

		try {
			Timestamp current = new Timestamp(System.currentTimeMillis()); // 当前时间
			cBase.setOriginId(originId);
			cBase.setCreator(creator);
			cBase.setOwner(creator);
			cBase.setCreated(current);
			cBase.setModified(current);
			session.save(cBase); // ?????

			// 查询max cid
			@SuppressWarnings("unchecked")
			List<Integer> results = session
					.createCriteria(ClientBase.class)
					.setMaxResults(1)
					.setProjection(
							Projections.projectionList().add(
									Projections.max("cid"))

					).list();
			Integer maxId = results.get(0);
			ClientOwner co = new ClientOwner();
			co.setId(new ClientOwnerId(maxId, owner));
			co.setModified(current);
			session.save(co); // save ClientOwner

			cExtend.setCid(maxId);
			cExtend.setOwner(creator);
			cExtend.setModified(current);
			cExtend.setCreated(current);
			session.save(cExtend);

			for (ClientPhone clientPhone : phoneList) {// 保存电话
				clientPhone.setCid(maxId);
				clientPhone.setCreated(current);
				clientPhone.setCreator(creator);
				session.merge(clientPhone); // 为什么save就会报错

			}

			tx.commit();
			return maxId;
		} catch (Exception e) {
			tx.rollback();
			e.printStackTrace();
			throw new Exception("新增失败");

		} finally {
			session.close();
		}

	}

	// 已经被上面方法包含了
	// public boolean editClient(ClientBase cBase, ClientExtend cExtend,
	// String phones){
	// Session session = clientBaseDao.getSessionFactory().getCurrentSession();
	// Transaction tx = session.beginTransaction();
	// //
	//
	//
	//
	// tx.commit();
	// return true;
	// }
	//

	/**
	 * cid对应的详细信息 不要用在ajax中
	 */

	/**
	 * @deprecated
	 */
	public ClientDetail showDetail(Integer cid, Integer owner) {
		ClientDetail clientDetail = new ClientDetail();
		ClientBase cb = clientBaseDao.findByHql(
				"from ClientBase b where b.id.cid=" + cid).get(0);
		ClientExtend ce = clientExtendDao.findByHql(
				"from ClientExtend b where b.id.cid=" + cid + " and b.owner="
						+ owner).get(0);
		List<ClientPhone> phones = clientPhoneDao
				.findByHql("from ClientPhone p where p.cid='" + cid + "'");
		clientDetail.setClientBase(cb);
		clientDetail.setClientExtend(ce);
		return clientDetail;
	}

	/**
	 * 功能： 按照设定好的排序条件进行简单分页排序，可以通过json工具 打印到jsp页面上 待完成： 可以仿照着
	 * 写一个类似的高级查询的方法，可以按关键字查询
	 * 
	 * @param owner
	 *            所有者
	 * @param queryType
	 *            查询类型枚举
	 * @param page
	 *            页数 0开始
	 * @param pageNum
	 *            每页条数
	 * @param isDesc
	 *            是否倒序
	 * @return
	 */

	public List<ClientDetail> showDetailList(Integer owner,
			QUERY_TYPE queryType, int page, int pageNum, boolean isDesc) {
		List<ClientDetail> scs = new ArrayList<ClientDetail>();
		Session session = clientBaseDao.getSessionFactory().getCurrentSession();
		try {
			List<Integer> cids = showCidList(owner, queryType, page, pageNum,
					isDesc);

			List<ClientBase> cbs = new ArrayList<ClientBase>();
			List<ClientExtend> ces = new ArrayList<ClientExtend>();

			AddressService adds = AddressService.getInstance();
			session.beginTransaction();
			Query query = null;
			for (Integer _cid : cids) {
				query = session.createQuery("from ClientBase b where b.cid='"
						+ _cid + "'");
				ClientBase cb = (ClientBase) query.uniqueResult();
				ClientDetail sc = new ClientDetail();
				sc.setClientBase(cb);
				query = session
						.createQuery("from ClientExtend e where e.id.cid='"
								+ _cid + "' and e.owner='" + owner.toString()
								+ "'");
				ClientExtend ce = (ClientExtend) query.uniqueResult();
				sc.setClientExtend(ce);

				query = session.createQuery("from ClientPhone p where p.cid='"
						+ _cid + "'");
				List<ClientPhone> cps = (List<ClientPhone>) query.list();
				sc.setClientPhones(cps);

				
				scs.add(sc);

			}

			session.beginTransaction().commit();
		} finally {
			session.close();
		}
		return scs;

	}

	
	
	
	
	
	/**
	 * 功能： 主要是作为getDetailList的配套方法，为了节省资源先找到cid的list 然后通过getDetailList获得对应的详细信息
	 * 
	 * @param owner
	 *            客户的拥有者id
	 * @param page
	 *            从0开始
	 * @param pageNum
	 *            每页记录数
	 * @param queryType
	 *            排序条件枚举项
	 * @param isDesc
	 *            是否倒序
	 * @return
	 */

	public List<Integer> showCidList(Integer owner, QUERY_TYPE queryType,
			int page, int pageNum, boolean isDesc) {
		Session session = clientBaseDao.getSessionFactory().getCurrentSession();
		List<Integer> cIds = new ArrayList<Integer>(); // cid list
	
		Transaction tx = session.beginTransaction();
	try{

		switch (queryType) {
		case DEFAULT:
		case MODIFIED:
			@SuppressWarnings("unchecked")
			Criteria criteria = session.createCriteria(ClientOwner.class);
			criteria.add(Restrictions.eq("owner", owner));
			criteria.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria.setProjection( // 设置列
			Projections.projectionList().add(Projections.property("id.cid")) // <--注意对复合主键查询的方法
			);
			if (isDesc) // 排序
				criteria.addOrder(Order.desc("modified"));
			else
				criteria.addOrder(Order.asc("modified"));

			List<Integer> results = criteria.list();
			for (Integer i : results) {
				cIds.add(i);
			}
			break;
		case CREATED:
			@SuppressWarnings("unchecked")
			Criteria criteria2 = session.createCriteria(ClientExtend.class);
			criteria2.add(Restrictions.eq("owner", owner));
			criteria2.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria2.setProjection( // 设置列
					Projections.projectionList().add(
							Projections.property("id.cid")) // <--注意对复合主键查询的方法
					);
			if (isDesc) // 排序
				criteria2.addOrder(Order.desc("created"));
			else
				criteria2.addOrder(Order.asc("created"));

			List<Integer> results2 = criteria2.list();
			for (Integer i : results2) {
				cIds.add(i);
			}
			break;
		case CLIENT_TYPE:
			@SuppressWarnings("unchecked")
			Criteria criteria3 = session.createCriteria(ClientExtend.class);
			criteria3.add(Restrictions.eq("owner", owner));
			criteria3.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria3.setProjection( // 设置列
					Projections.projectionList().add(
							Projections.property("id.cid")) // <--注意对复合主键查询的方法
					);
			if (isDesc) // 排序
				criteria3.addOrder(Order.desc("clientType"));
			else
				criteria3.addOrder(Order.asc("clientType"));

			List<Integer> results3 = criteria3.list();
			for (Integer i : results3) {
				cIds.add(i);
			}
			break;
		case SELL_PLAN:
			@SuppressWarnings("unchecked")
			Criteria criteria4 = session.createCriteria(ClientExtend.class);
			criteria4.add(Restrictions.eq("owner", owner));
			criteria4.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria4.setProjection( // 设置列
					Projections.projectionList().add(
							Projections.property("id.cid")) // <--注意对复合主键查询的方法
					);
			if (isDesc) // 排序
				criteria4.addOrder(Order.desc("sellPlan"));
			else
				criteria4.addOrder(Order.asc("sellPlan"));

			List<Integer> results4 = criteria4.list();
			for (Integer i : results4) {
				cIds.add(i);
			}
			break;
		case PROVINCE:
			@SuppressWarnings("unchecked")
			Criteria criteria5 = session.createCriteria(ClientBase.class);
			criteria5.add(Restrictions.eq("owner", owner));
			criteria5.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria5.setProjection( // 设置列
					Projections.projectionList().add(
							Projections.property("cid")) //
					);
			if (isDesc) // 排序
				criteria5.addOrder(Order.desc("provinceId"));
			else
				criteria5.addOrder(Order.asc("provinceId"));

			List<Integer> results5 = criteria5.list();
			for (Integer i : results5) {
				cIds.add(i);
			}
			break;
		case CITY:
			@SuppressWarnings("unchecked")
			Criteria criteria6 = session.createCriteria(ClientBase.class);
			criteria6.add(Restrictions.eq("owner", owner));
			criteria6.setMaxResults(pageNum).setFirstResult(pageNum * page); // 分页
			criteria6.setProjection( // 设置列
					Projections.projectionList().add(
							Projections.property("cid")));
			if (isDesc) // 排序
				criteria6.addOrder(Order.desc("cityId"));
			else
				criteria6.addOrder(Order.asc("cityId"));

			List<Integer> results6 = criteria6.list();
			for (Integer i : results6) {
				cIds.add(i);
			}
			break;

		}

		tx.commit();
	}finally{
		session.close();
		
	}
		return cIds;
	}


	
	/**
	 * 返回：1-OK -1：格式不对 -2：已有
	 * @param phoneNumber
	 * @return
	 */
	public int checkPhone(String phoneNumber) {
		boolean isMobile = ClientTool.isMobileNO(phoneNumber);
		if (!isMobile)
			return -1;
		int count = clientPhoneDao.findByHql("from ClientPhone c where c.phone='" + phoneNumber + "'").size();
		if (count > 0)
			return -2;
		else
			return 1;
	}

	// ############################ 分割线
	// ############################################################
	public ClientPhoneDao getClientPhoneDao() {
		return clientPhoneDao;
	}

	public void setClientPhoneDao(ClientPhoneDao clientPhoneDao) {
		this.clientPhoneDao = clientPhoneDao;
	}

	public ClientBaseDao getClientBaseDao() {
		return clientBaseDao;
	}

	public void setClientBaseDao(ClientBaseDao clientBaseDao) {
		this.clientBaseDao = clientBaseDao;
	}

	public ClientExtendDao getClientExtendDao() {
		return clientExtendDao;
	}

	public void setClientExtendDao(ClientExtendDao clientExtendDao) {
		this.clientExtendDao = clientExtendDao;
	}

	// TEST
	public static void main(String[] args) throws Exception {
		ClientService cs = ClientService.getInstance();
//		boolean r=cs.isNameCityRepeat("冷文", "53060",0);
		int r = cs.updateLastTime(5);
		System.out.println(r);
//		int r=cs.checkPhone("17799999991");
//		System.out.println(cs.getName(2399));
		
//		int i=cs.clientBaseDao.getSessionFactory().openSession().getNamedQuery("com.base.bean.clientbase.test").list().size();
//		System.out.println(i);
		
		// // 测试add client
		// ClientBase cb=new ClientBase();
		// ClientExtend ce=new ClientExtend();
		// List<ClientPhone> cPhones=new ArrayList<ClientPhone>();
		// cb.setName("bob");
		// cb.setComName("hf");
		// cb.setProvinceId("610000");
		// cb.setCityId("611100");
		// cb.setAreaId("611111");
		// Integer uid=new Integer(1); //正式部署时 用会话中保存的用户id 或openId中对应的id
		// ce.setId(new ClientExtendId(2,uid)); //不能重复
		//
		// String phones="15100000018,15100000028";
		// ClientService.getInstance().addClient(cb, ce, phones);

		// Integer owner,int type,int page,int pageNum,boolean isDesc

		// 测试2
		// List<Integer> r = ClientService.getInstance().getCidList(1,
		// ClientService.QUERY_TYPE.PROVINCE, 0, 10,
		// false);
		// for (Integer i : r) {
		// System.out.println(i.toString());
		// }

		// List<ClientDetail> scs=ClientService.getInstance().showDetailList(1,
		// ClientService.QUERY_TYPE.PROVINCE, 0, 10,
		// false);
		//
		// ClientExtend cb=new ClientExtend();
		//
		// System.out.println(JsonTool.obj2json(scs));

		// for(ClientDetail sc:scs){
		// System.out.println(sc.getName()+sc.getCityName()+sc.getAreaName());
		// }

	}

}
